package my.springboot.service.impl;

import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import my.springboot.exception.BaseException;
import my.springboot.po.vo.ReturnCode;
import my.springboot.service.WechatPayService;
import org.apache.http.Consts;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付
 * @author fengbo
 */
@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {


    @Value("${system.resource.wx-app-id}")
    private String appId;
    @Value("${system.resource.wx-mch-id}")
    private String mchId;
    @Value("${system.resource.wx-mch-key}")
    private String mchKey;

    @Override
    public String payToChange(Integer amount, String tradeNo, String openId, String ip) throws Exception {

        // 了解SSL原理
        SSLContext sslContext;
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("wechat/apiclient_cert.p12")) {
            KeyStore trustStore = KeyStore.getInstance("PKCS12");
            trustStore.load(inputStream, mchId.toCharArray());
            sslContext = SSLContexts
                    .custom()
                    .loadKeyMaterial(trustStore, mchId.toCharArray())
                    .build();
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException e) {
            log.error("Parse ssl context failed! msg=[{}]", e.getMessage(), e);
            throw new BaseException(ReturnCode.WECHAT_PAY_ERROR);
        }

        String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        HttpPost httpPost = new HttpPost(url);

        Map<String, String> param = new HashMap<>(16);
        param.put("mch_appid", appId);
        param.put("mchid", mchId);
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        param.put("partner_trade_no", tradeNo);
        param.put("openid", openId);
        param.put("check_name", "NO_CHECK");
        param.put("amount", String.valueOf(amount));
        param.put("desc", "一起薅羊毛的用户[" + openId + "]提现");
        param.put("spbill_create_ip", ip);

        StringEntity httpEntity = new StringEntity(WXPayUtil.generateSignedXml(param, mchKey), Consts.UTF_8);
        httpPost.setEntity(httpEntity);
        httpEntity.setContentEncoding(Consts.UTF_8.toString());
        httpEntity.setContentType(ContentType.APPLICATION_XML.getMimeType());
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
                .build();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {
            return EntityUtils.toString(response.getEntity(), Consts.UTF_8);
        } catch (Exception e) {
            log.error("调用微信支付失败! msg=[{}]", e.getMessage(), e);
            throw new BaseException(ReturnCode.WECHAT_PAY_ERROR);
        }
    }
}
